/*
Client socket,use async select mode.
add by szz
*/

#ifndef _ASYNC_COMM_H_
#define _ASYNC_COMM_H_

#include "Common.h"
#include "communication/CircularBuffer.h"
#include "CommunicationDef.h"

class Session;
class DataPacket;
class AsyncComm
{
	const static uint32 HEART_BEAT_TIME  = 1000;
public:
	static void InitNetwork();
	// Constructor. If fd = 0, it will be assigned 
	AsyncComm();

	virtual bool InitFD(HANDLE_FD fd, Session* pSession);
	// Destructor.
	virtual ~AsyncComm();

	// Open a connection to another machine.
	virtual bool Connect(const char * Address);
	virtual void Disconnect();
	

	/* Implementable methods */

	// Called when data is received.
	virtual void OnRead();
	virtual void OnWrite();
	// Called when a connection is first successfully established.
	virtual void OnConnect();

	// Called when the socket is disconnected from the client (either forcibly or by the connection dropping)
	virtual void OnDisconnect(int32 errorCode);

	virtual void Update(int32 deltaTime);

	
	/* Sending Operations */
	// Locks sending mutex, adds bytes, unlocks mutex.
	virtual bool Send(const uint8* Bytes, uint32 Size);

	// Burst system - Locks the sending mutex.
	inline void BurstBegin() {  }
	bool BurstSend(const uint8 * Bytes, uint32 Size);
	void BurstPush();
	inline void BurstEnd() { }
	std::string GetRemoteAddress();
	inline int GetFd() { return m_fd; }

	inline bool IsConnected() { return m_connected; }

	inline CircularBuffer& GetReadBuffer() { return readBuffer; }
	inline CircularBuffer& GetWriteBuffer() { return writeBuffer; }

public:
	void SendPacket(DataPacket* packet);
	
	void UpdateHeartPing(int32 deltaTime,bool bMapPing );
	void UpdateQueuedPackets();
	void OutPacket(uint16 opcode, size_t len, const void* data);
	OUTPACKET_RESULT _OutPacket(uint16 opcode, size_t len, const void* data);

	virtual uint32 GetLastError() { return 0; }

protected:
	virtual bool CloseFD() = 0;
	virtual bool _NonblockingFD() = 0 ;
	virtual int _RawReadData(char* pBuff, uint32 nBuffLen )	= 0;
	virtual int _RawWriteDate(char* pBuff, uint32 nDataLen ) = 0;

	void WriteCallback();
	bool ReadDataCallback();
	// Called when connection is opened.
	virtual void _Reset();
	virtual void _OnConnect();

	CircularBuffer readBuffer;
	CircularBuffer writeBuffer;

	bool		m_connected;
	HANDLE_FD	m_fd;
	fd_set		m_read,m_write,m_error;

	uint32		m_BytesSent;
	uint32		 m_BytesRecieved;
	uint32		m_nRemaining;
	uint32		m_Opcode;
	uint32		m_nSize;
	Session* m_pSession;

	std::queue<DataPacket*> m_SendQueue;
public:	
	int32 m_lastPong;
	int32 m_timeSendPing;
};

#endif
